import React from 'react';
import {connect} from "dva";
import {AnyAction, Dispatch} from "redux";
import {Spin, Tree} from 'antd';
import {ConnectState} from "@/models/connect";
import { OptionType } from '@/types/common';
import {DataNode, EventDataNode, Key} from "rc-tree/lib/interface";

interface RegionTreeProps{
  value?: (string | number)[];
  onChange?: (value:(string | number)[],type?:string)=>void;
  dispatch: Dispatch<AnyAction>;
  list:OptionType[];
  loading: boolean|undefined;
}

interface RegionTreeState{
  loadedKeys?: (string | number)[];
  selectedKeys?: (string | number)[];
  expandedKeys?: (string | number)[];
}

class RegionTree extends React.Component<RegionTreeProps,RegionTreeState> {

  state={
    loadedKeys:[],
    selectedKeys:this.props.value||[],
    expandedKeys:[],
  }

  static getDerivedStateFromProps(nextProps: RegionTreeProps) {
    if ('value' in nextProps) {
      return { selectedKeys: nextProps.value || [] };
    }
    return null;
  }

  componentDidMount(): void {
    this.props.dispatch({
      type: 'region/queryProvince',
    });
  }

  loadData = (node:EventDataNode):Promise<void> => {
    let { loadedKeys } = this.state;
    // @ts-ignore
    loadedKeys.push(node.props.data.key);
    this.setState({
      loadedKeys: loadedKeys,
    });
    // @ts-ignore
    const parentId=node.props.data.parentId;
    return new Promise((resolve) => {
      if (node.children) {
        resolve();
      } else {
        if(parentId){
          const {dispatch} = this.props;
          dispatch({
            type: 'region/queryDistrict',
            payload: [parentId,node.key],
          })
          // @ts-ignore
          .then(()=>{
            resolve();
          });
        }else{
          const {dispatch} = this.props;
          dispatch({
            type: 'region/queryCity',
            payload: [node.key],
          })
          // @ts-ignore
          .then(()=>{
            resolve();
          });
        }
      }
    });
  };

  onSelect = (value: (string | number)[],info:{
      event: 'select';
      selected: boolean;
      node: EventDataNode;
      selectedNodes: DataNode[];
      nativeEvent: MouseEvent;
    }) => {
    let type;
    const {selectedNodes}=info;
    if(selectedNodes.length>0){
      // @ts-ignore
      type=selectedNodes[0].type;
    }
    if (!('value' in this.props)) {
      this.setState({ selectedKeys:value });
    }
    const { onChange } = this.props;
    if (onChange) {
      onChange(value,type);
    }
  };


  onExpand = (expandedKeys: Key[], info: {node: EventDataNode; expanded: boolean; nativeEvent: MouseEvent;}) => {
    this.setState({expandedKeys: expandedKeys});
  };

  renderTree = (options:OptionType[]):({ children: DataNode[]; title: any | string | undefined; type: any; isLeaf: boolean | undefined; key: any | string | number | undefined; parentId: any } | { title: any | string | undefined; type: any; isLeaf: boolean | undefined; key: any | string | number | undefined; parentId: any })[] =>{
    return (
      options.map(option => {
        if (option.children) {
          return {
            key:option.id,
            parentId:option.parentId,
            isLeaf:option.isLeaf,
            title:option.name,
            type:option.type,
            children:this.renderTree(option.children)
          }
        }
        return {
          key:option.id,
          parentId:option.parentId,
          isLeaf:option.isLeaf,
          title:option.name,
          type:option.type,
        }
      })
    )
  }

  render() {

    const { list,loading } = this.props;
    const { loadedKeys,selectedKeys,expandedKeys } = this.state;

    return (
      <Spin spinning={!!loading}>
        <Tree
          treeData={this.renderTree(list)}
          loadedKeys={loadedKeys}
          selectedKeys={selectedKeys}
          expandedKeys={expandedKeys}
          loadData={this.loadData}
          onSelect={this.onSelect}
          onExpand={this.onExpand}
        />
      </Spin>
    );
  }
}

export default connect(({loading,region}:ConnectState) => ({
  list:region.list,
  loading: loading.effects['region/queryProvince']
    || loading.effects['region/queryCity']
    || loading.effects['region/queryDistrict']
}))(RegionTree);

